事前共有鍵(PSK) - Noise Protocol Framework (12)
Noiseプロトコルでは、事前共有鍵(pre-shared symmetric key または単にPSK)モードがサポートされています。
これは、プロトコル開始前に両者が32バイトの鍵を共有している事を前提として、ハンドシェイクを開始するモードです。PSKモードを利用することにより、セキュリティが強化されます。
暗号化関数
PSKモードでは、PSKをSymmetricStateの鍵とh値に混ぜるために、SymmetricState#MixKeyAndHashメソッドを使います。
ちなみに、SymmetricState#MixKeyAndHashメソッドのRubyによる実装は下記の通りです。このinput_key_materialにPSKを使います。
code: symmetric_state.rb
def mix_key_and_hash(input_key_meterial)
@ck, temp_h, temp_k = @protocol.hkdf_fn.call(@ck, input_key_meterial, 3)
mix_hash(temp_h)
temp_k = truncate(temp_k) # If HASHLEN is 64 then truncates temp_k to 32 bytes
@cipher_state.initialize_key(temp_k)
end
ハンドシェイクトークン
PSKモードでのハンドシェイクでは、ハンドシェイクパターン内で"psk"トークンが使用されます。複数回使用される場合もあります。
このトークンはメッセージパターンの中に使用されます。プレメッセージパターンには使用されません。
PSKモードでない場合は、"e"トークンがプレメッセージパターンまたはメッセージパターンに使用された時にはSymmetricState#MixHash(e.public_key)がコールされます。一方で、PSKモードでは、SymmetricState#MixHash(e.public_key)が呼ばれたあとで、SymmetricState#MixKey(e.public_key)を呼び出す必要があります。これによって、PSKモードでは、一時鍵"e"をnonceとしてランダム化した暗号鍵を確実に使用するようにしています。
妥当性に対する要件
同一の鍵の再利用を防ぐため、"psk"トークンを使用したハンドシェイクパターンは以下のルールに従う必要があります。
"psk"トークンの前後のどちらかに"e"トークンを送信していない限り、"psk"トークン処理後に暗号化されたデータを送信することはできません。
このルールはPSKから導出されるkの値が、一時公開鍵"e"を使ったSymmetricState#MixKey(e.public_key)によってランダム化されていない限りは暗号化に使用されないことを保証します。
パターンの記述方法
PSKモードを使用する場合のハンドシェイクパターンの記述には"psk"修飾子が使用されます。
"psk0"は最初のハンドシェイクメッセージの先頭に"psk"トークンをおきます。
"psk1"は最初のハンドシェイクメッセージの最後に"psk"トークンをおきます。
"psk2"は2番目のハンドシェイクメッセージの最後に"psk"トークンをおきます。
以下、同様にpskX(Xは数字)でpskのトークンを記述します。以下は一方向ハンドシェイクパターンでの記述例です(左側にnon-PSKなパターン、右側にそのPSKモードのパターン)
X: Xpsk1:
<- s <- s
... ...
-> e, es, s, ss -> e, es, s, ss, psk
上記の例で、Xには(psk0ではなく)psk1が推奨されることに注意してください。これはXがイニシエーターの静的公開鍵"s"を暗号化して送信するためです。レスポンダーは静的公開鍵を複合するまでPSKを特定できない可能性があるため、"s"の送信したあとに"psk"を送信するのが都合がよく、したがって、"psk0"よりも"psk1"の方がよいとされています。
以下は、対話的なハンドシェイクパターンの例です。
NN: NNpsk0:
-> e -> psk, e
<- e, ee <- e, ee
NN: NNpsk2:
-> e -> e
<- e, ee <- e, ee, psk
NX: NXpsk2:
-> e -> e
<- e, ee, s, es <- e, ee, s, es, psk
XN: XNpsk3:
-> e -> e
<- e, ee <- e, ee
-> s, se -> s, se, psk
これらはあくまで一例なので、実際にはもっと多くのPSKモードのパターンが考えられます。複数のPSKを使った、XXpsk0+psk3のようなパターンも定義することができます。